#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <pthread.h>
#include "msg_queue_peer.h"
#include "shmem.h"
#include "cJSON.h"

#define SHARED_MEM_NAME "point_table_shm"
#define SEM_NAME "/point_table_shm_sem"

struct msgbuf
{
    long mtype;
    int key;
    int value;
};
struct msgbuf stm32_recv, modbus_recv; // 使用独立缓冲区

// 数据类型定义
typedef enum
{
    TYPE_BOOL = 1,  // 布尔类型
    TYPE_INT = 2,   // 整数类型
    TYPE_FLOAT = 3, // 浮点类型
} DataType;

// STM32设备点表项
typedef struct
{
    uint16_t key;   // 点表键值
    char name[32];  // 点表名称
    DataType type;  // 数据类型
    uint8_t status; // 状态标志(0=无效,1=有效)
    union
    {
        int int_value;
        float float_value;
        int bool_value;
    } value;
} STM32Item;

// Modbus设备点表项
typedef struct
{
    uint16_t key;   // 点表键值
    char name[32];  // 点表名称
    uint16_t addr;  // Modbus地址
    DataType type;  // 数据类型
    uint8_t status; // 状态标志(0=无效,1=有效)
    union
    {
        int int_value;
        float float_value;
        int bool_value;
    } value;
} ModbusItem;

// 完整配置结构体
typedef struct
{
    int stm32_count;            // STM32点表项数量
    STM32Item stm32_items[100]; // 与写入程序保持一致

    int modbus_count;             // Modbus点表项数量
    ModbusItem modbus_items[100]; // 与写入程序保持一致

    // 其他配置信息
    char version[10]; // 配置版本
    struct
    {
        int type;   // 报告类型
        int period; // 报告周期
    } report;
    struct
    {
        char addr[20]; // MQTT服务器地址
        int port;      // MQTT服务器端口
    } mqtt_server;
    struct
    {
        char addr[20]; // Modbus设备地址
        int port;      // Modbus设备端口
    } mb_dev;
    struct
    {
        char addr[20]; // Modbus应用地址
        int port;      // Modbus应用端口
    } mb_app;
} ConfigData;

// 全局变量，用于存储配置数据
ConfigData *config = NULL;

int clientfd;
// 线程函数
void *msg_queue_read_thread(void *arg)
{
    while (1)
    {
        printf("读取消息队列中 stm32 中。。。\n");
        // 尝试接收stm32队列消息
        if (msg_queue_recv("stm32", &stm32_recv, sizeof(stm32_recv), 0, IPC_NOWAIT) > 0)
        {
            printf("stm32: key=%d, value=%d\n", stm32_recv.key, stm32_recv.value);

            // 序列化JSON数据
            cJSON *root = cJSON_CreateObject();
            cJSON *stm32Array = cJSON_CreateArray();
            cJSON *item;
            item = cJSON_CreateObject();
            cJSON_AddNumberToObject(item, "key", stm32_recv.key);
            cJSON_AddNumberToObject(item, "value", stm32_recv.value);
            cJSON_AddItemToArray(stm32Array, item);
            cJSON_AddItemToObject(root, "data", stm32Array);
            cJSON_AddNumberToObject(root, "type", stm32_recv.mtype);
            char *jsonString = cJSON_Print(root);
            printf("%s\n", jsonString);
            printf("clientfd:%d\n", clientfd);
            // 发送JSON数据
            if (send(clientfd, jsonString, strlen(jsonString), 0) == -1)
            {
                perror("send error");
                free(jsonString);
                cJSON_Delete(root);
                continue;
            }
            printf("发送数据成功\n");
            free(jsonString);
            cJSON_Delete(root);
        }
        else if (errno != ENOMSG)
        { // 忽略"队列空"错误
            perror("stm32 recv error");
        }
        sleep(1);
    }
}

int main(int argc, char const *argv[])
{
    struct shm_param shm;
    sem_t *shm_sem;
    // 打开信号量
    shm_sem = sem_open(SEM_NAME, 0);
    if (shm_sem == SEM_FAILED)
    {
        perror("Failed to open semaphore");
        return 1;
    }

    // 计算共享内存所需大小
    const size_t SHARED_MEM_SIZE = sizeof(ConfigData);
    printf("ConfigData size: %zu bytes\n", SHARED_MEM_SIZE);

    // 初始化共享内存（这里只是获取信息，不会重新创建共享内存）
    if (shm_init(&shm, SHARED_MEM_NAME, SHARED_MEM_SIZE, 0) != 0)
    {
        fprintf(stderr, "Failed to initialize shared memory\n");
        sem_close(shm_sem);
        return 1;
    }

    // 获取共享内存地址
    void *shm_addr = shm_getaddr(&shm);
    if (shm_addr == NULL)
    {
        fprintf(stderr, "Failed to attach shared memory\n");
        sem_close(shm_sem);
        return 1;
    }
    printf("shm_addr: %p\n", shm_addr);

    // 加锁读取共享内存
    sem_wait(shm_sem);
    // 将共享内存地址转换为ConfigData结构体指针
    ConfigData *config = (ConfigData *)shm_addr;
    // 解锁
    sem_post(shm_sem);

    // 创建一个套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("套接字创建失败");
        return -1;
    }
    printf("套接字创建成功，文件描述符为：%d\n", sockfd);

    // 设置套接字选项，允许地址重用
    int opt = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
    {
        perror("设置套接字选项失败");
        return -1;
    }

    // 指定网络地址和端口
    struct sockaddr_in serveraddr, clientaddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = INADDR_ANY; // 监听所有网络接口
    serveraddr.sin_port = htons(8886);       // 监听端口号
    int len = sizeof(clientaddr);

    // 绑定套接字到指定的网络地址和端口
    if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("绑定失败");
        return -1;
    }
    printf("绑定成功\n");
    // 监听连接请求
    if (listen(sockfd, 5) < 0)
    {
        perror("监听失败");
        return -1;
    }
    printf("开始监听连接请求...\n");
    
    // 接受客户端连接
    clientfd = accept(sockfd, (struct sockaddr *)&clientaddr, (socklen_t *)&len);

    printf("客户端连接成功，文件描述符为：%d\n", clientfd);
    // 创建子线程用来读取消息队列
    pthread_t tid;
    if (pthread_create(&tid, NULL, (void *)msg_queue_read_thread, NULL) != 0)
    {
        perror("创建线程失败");
        return -1;
    }
    printf("创建线程成功\n");

    // 循环接收数据
    int count = 0;
    while (1)
    {

        char buffer[1024];
        int bytesRead = recv(clientfd, buffer, sizeof(buffer), 0);
        if (bytesRead < 0)
        {
            perror("接收数据失败");
            return -1;
        }
        buffer[bytesRead] = '\0'; // 添加字符串结束符
        printf("接收到的数据%d:%s\n", ++count, buffer);

        // 解析JSON数据
        cJSON *root = cJSON_Parse(buffer);
        cJSON *stm32Array = cJSON_GetObjectItem(root, "stm32");
        cJSON *item;

        // 加锁写入共享内存
        sem_wait(shm_sem);
        config->stm32_count = cJSON_GetArraySize(stm32Array);

        for (int i = 0; i < cJSON_GetArraySize(stm32Array); i++)
        {
            item = cJSON_GetArrayItem(stm32Array, i);
            config->stm32_items[i].key = cJSON_GetObjectItem(item, "key")->valueint;
            strcpy(config->stm32_items[i].name, cJSON_GetObjectItem(item, "name")->valuestring);
            config->stm32_items[i].type = cJSON_GetObjectItem(item, "type")->valueint;
            config->stm32_items[i].status = cJSON_GetObjectItem(item, "status")->valueint;

            if (config->stm32_items[i].type == TYPE_BOOL)
            {
                config->stm32_items[i].value.bool_value = cJSON_GetObjectItem(item, "value")->valueint;
            }
            else if (config->stm32_items[i].type == TYPE_INT)
            {
                config->stm32_items[i].value.int_value = cJSON_GetObjectItem(item, "value")->valueint;
            }
            else if (config->stm32_items[i].type == TYPE_FLOAT)
            {
                config->stm32_items[i].value.float_value = cJSON_GetObjectItem(item, "value")->valuedouble;
            }
        }
        // 使用后解锁
        sem_post(shm_sem);
    }
    // 关闭信号量
    sem_close(shm_sem);
    // 关闭套接字
    close(sockfd);
    close(clientfd);
    printf("套接字关闭\n");
    return 0;
}
